/**
 * CL_Animate动画计算插件
 * Author: 陆楚良
 * Version: 2.0.3
 * Date: 2014/12/17
 * QQ: 519998338
 *
 * https://git.oschina.net/luchg/CL_Animate.js.git
 *
 * License: http://www.apache.org/licenses/LICENSE-2.0
 **/
!function(){

function Animate(){Animate.prototype.init.apply(this, [].slice.call(arguments))}
Animate.fps = 60;
Animate.easing = {
	"default": "swing",
	linear: function (t) {
		return t
	},
	swing: function (t) {
		return 0.5-Math.cos(t*Math.PI)/2
	},
	easeInQuad : function (t) {
		return t*t
	},
	easeOutQuad: function (t) {
		return -1*t*(t-2)
	},
	easeInOutQuad: function (t) {
		if ((t/=0.5) < 1) return 0.5*t*t;
		return -0.5 * ((--t)*(t-2) - 1);
	},
	easeInCubic: function (t) {
		return t*t*t;
	},
	easeOutCubic: function (t) {
		return ((t=t-1)*t*t + 1);
	},
	easeInOutCubic: function (t) {
		if ((t/=0.5) < 1) return 0.5*t*t*t;
		return 0.5*((t-=2)*t*t + 2);
	},
	easeInQuart: function (t) {
		return t*t*t*t;
	},
	easeOutQuart: function (t) {
		return -1 * ((t-=1)*t*t*t - 1);
	},
	easeInOutQuart: function (t) {
		if ((t/=0.5) < 1) return 0.5*t*t*t*t;
		return -0.5 * ((t-=2)*t*t*t - 2);
	},
	easeInQuint: function (t) {
		return t*t*t*t*t;
	},
	easeOutQuint: function (t) {
		return (t-=1)*t*t*t*t + 1;
	},
	easeInOutQuint: function (t) {
		if ((t/=0.5) < 1) return 0.5*t*t*t*t*t;
		return 0.5*((t-=2)*t*t*t*t + 2);
	},
	easeInSine: function (t) {
		return -1 * Math.cos(t * (Math.PI/2)) + 1;
	},
	easeOutSine: function (t) {
		return Math.sin(t * (Math.PI/2));
	},
	easeInOutSine: function (t) {
		return -0.5 * (Math.cos(Math.PI*t) - 1);
	},
	easeInExpo: function (t) {
		return (t==0) ? 0 : Math.pow(2, 10 * (t - 1));
	},
	easeOutExpo: function (t) {
		return (t==1) ? 1 : -Math.pow(2, -10 * t) + 1;
	},
	easeInOutExpo: function (t) {
		if (t==0 || t==1) return t;
		if ((t/=0.5) < 1) return 0.5 * Math.pow(2, 10 * (t - 1));
		return 0.5 * (-Math.pow(2, -10 * --t) + 2);
	},
	easeInCirc: function (t) {
		return -1 * (Math.sqrt(1 - t*t) - 1);
	},
	easeOutCirc: function (t) {
		return Math.sqrt(1 - (t-=1)*t);
	},
	easeInOutCirc: function (t) {
		if ((t/=0.5) < 1) return -0.5 * (Math.sqrt(1 - t*t) - 1);
		return 0.5 * (Math.sqrt(1 - (t-=2)*t) + 1);
	},
	easeInElastic: function (t) {
		var s=1.70158;var p=0;var a=1;
		if (t==0 || t==1) return t; if (!p) p=0.3;
		if (a < Math.abs(1)) { a=1; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (1/a);
		return -a*Math.pow(2,10*(t-=1)) * Math.sin( (t-s)*(2*Math.PI)/p );
	},
	easeOutElastic: function (t) {
		var s=1.70158;var p=0;var a=1;
		if (t==0 || t==1) return t; if (!p) p=0.3;
		if (a < Math.abs(1)) { a=1; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (1/a);
		return a*Math.pow(2,-10*t) * Math.sin( (t-s)*(2*Math.PI)/p ) + 1;
	},
	easeInOutElastic: function (t) {
		var s=1.70158;var p=0;var a=1;
		if (t==0) return 0;  if ((t/=0.5)==2) return 1;  if (!p) p=0.3*1.5;
		if (a < Math.abs(1)) { a=1; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (1/a);
		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t-s)*(2*Math.PI)/p ));
		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t-s)*(2*Math.PI)/p )*.5 + 1;
	},
	easeInBack: function (t) {
		var s = 1.70158;
		return t*t*((s+1)*t - s);
	},
	easeOutBack: function (t) {
		var s = 1.70158;
		return (t-=1)*t*((s+1)*t + s) + 1;
	},
	easeInOutBack: function (t) {
		var s = 1.70158; 
		if ((t/=0.5) < 1) return 0.5*(t*t*(((s*=(1.525))+1)*t - s));
		return 0.5*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2);
	},
	easeInBounce: function (t) {
		return 1 - Animate.easing.easeOutBounce (1-t);
	},
	easeOutBounce: function (t) {
		if (t < (1/2.75)) {
			return 7.5625*t*t;
		} else if (t < (2/2.75)) {
			return 7.5625*(t-=(1.5/2.75))*t + .75;
		} else if (t < (2.5/2.75)) {
			return 7.5625*(t-=(2.25/2.75))*t + .9375;
		} else {
			return 7.5625*(t-=(2.625/2.75))*t + .984375;
		}
	},
	easeInOutBounce: function (t) {
		if (t < 0.5) return Animate.easing.easeInBounce (t*2) * .5;
		return Animate.easing.easeOutBounce (t*2-1) * .5 + .5;
	}
};

Animate.prototype.run = function(callback,onStop){
	var timer;
	var self     = this;
	var beginTime= new Date;
	var fps      = typeof(Animate.fps) =="number"?Animate.fps :60;
	var duration = typeof(this._d)=="number"?this._d:1000;
	var ease     = (typeof(this._e)=="string" && typeof Animate.easing[this._e]=="function") ? this._e : Animate.easing["default"];
	var easing   = Animate.easing[ease];
	if(typeof easing!="function"){
		throw new TypeError("Animate.easing[\""+ease+"\"] type is a "+(typeof easing)+" not a function");
		return;
	}
	this._t = timer = setInterval(function(){
		var per = (new Date - beginTime) / duration;
		if(per>=1){
			callback.call(self,1, per);
			self.stop(timer,onStop);
		}else{
			callback.call(self, easing(per,0,1,1), per);
		}
	},parseInt(1000/fps));
	return timer;
}

Animate.prototype.stop = function(){
	var p,args  = [].slice.call(arguments);
	for( var i=0; i<args.length; i++){
		switch(typeof(args[i])){
			case "number":
				clearInterval(args[i]);p=1;break;
			case "function":
				args[i].call(this);break;
		}
	}
	!p && clearInterval(this._t);
	if(typeof(this._c)=="function")this._c();
	return this;
}

Animate.prototype.init = function(){
	var args  = [].slice.call(arguments);
	for( var i=0; (i<3 && i<args.length); i++){
		switch(typeof(args[i])){
			case "number":
				this._d = args[i];break;
			case "string":
				this._e = args[i];break;
			case "function":
				this._c = args[i];break;
		}
	}
	return this;
}



!function(window, undefined){
var getWidthOrHeight = function(element,name){
	var old,ret,cur = curCss(element);
		comp = parseFloat(cur[name]);
	old = element.style[name];
	element.style[name] = comp+"px";
	ret = comp+comp-parseFloat(cur[name]);
	element.style[name] = old;
	return ret+"px";
};
var curCss = function(element){
	return element.currentStyle?element.currentStyle:window.getComputedStyle(element,null);
}
var Css = function(element, name, value){
	if(typeof value=="string"){
		element.style[name] = value;
	}else{
		var istyle = element.style,
			fstyle = curCss(element);
		switch(typeof name){
			case "string":
				// 优先读取行内样式(行内样式无需转换)
				return (value!==true && istyle[name]) ? istyle[name] : (
						(name=="width" || name=="height") ? getWidthOrHeight(element, name) : (fstyle[name]||"")
					);
			case "object":
				var i;
				for(i in name){
					if(typeof i == "string"){
						name[i] = (value!==true && istyle[i]) ? istyle[i] : (
							(i=="width" || i=="height") ? getWidthOrHeight(element, i) : (fstyle[i]||"")
						);
					}
				}
				return name;
			default:
				return "";
		}
	}
};
var Tween = function(element, name, unit){
	var target = Css(element, name).match(rfxnum)[1],
		scale = 1,
		start = target,
		maxIterations = 20;
	do {
		scale = scale || ".5";
		start = start / scale;
		Css(element, name, start+unit);
	} while ( scale !== (scale = Css(element, name, true).match(rfxnum)[1] / target) && scale !== 1 && --maxIterations );
	return start;
};
var trim = function(str){
	if(String.prototype.trim)return str.trim();
	return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "");
};
var floatReg = /-?(0|[1-9][0-9]*)(\.[0-9]+)?/;
var floatRegAll = new RegExp(floatReg.source, "g");
var rfxnum = new RegExp("^("+floatReg.source+")([a-z%]*)$", "i");

Animate.prototype.easy = function(element, css, onStop) {
	var name,style={},c,g1,g2,i;
	if (Object.prototype.toString.call(css) !== '[object Array]'){
		for(name in css){
			style[name] = undefined;
		}
		style = Css(element, style);
		var start,end;
		for(name in style){
			start = trim(style[name]).match(rfxnum);
			end   = trim(css[name]+"").match(rfxnum);
			if(start && end){
				if(start[4]!==end[4]){
					style[name] = Tween(element, name, end[4])+end[4];
				}
			}
		}
	}else{
		style=css[0];
		css = css[1];
	}
	// 转成字符串
	for(name in css){
		css[name]	= String(  css[name]);
		style[name]	= String(style[name]);
	}
	return this.run(function(x){
		for(name in css){
			if(typeof(css[name])=="string" && typeof(style[name])=="string"){
				g1 = style[name].match(floatRegAll);
				g2 = css[name].match(floatRegAll);
				c  = css[name].replace(floatRegAll, "###");
				if(g1 && g2 && g1.length==g2.length){
					for(i=0;i<g1.length;i++){
						c = c.replace("###", parseFloat(g1[i])+(parseFloat(g2[i])-parseFloat(g1[i]))*x);
					}
				}
				element.style[name] = c;
			}
		}
	}, onStop);
}

}(this);


// RequireJS && SeaJS && GlightJS
if (typeof define === "function") {
    define(function() {
        return Animate;
    });

// NodeJS
} else if (typeof exports !== "undefined") {
    module.exports = Animate;
} else {
    this.CL_Animate = Animate;
}

}();